#include "GameObject.h"
GameObject::GameObject(std::vector<float>_position,std::string _name):
	m_shaderType(0),
	m_vertexes(),
	m_surfaces(),
	m_name(_name),
	m_isVisible(true),
	m_needToUpdateRenderingBuffer(false),
	m_needToUpdateTexture(false)
{
	m_transform = new Transform(_position);
}
GameObject::GameObject(std::vector<float>_position, std::vector<Vertex>_vertexes, std::vector<std::vector<int>>_surfaces, std::string _name):
	m_shaderType(0),
	m_vertexes(_vertexes),
	m_surfaces(_surfaces),
	m_name(_name),
	m_isVisible(true),
	m_needToUpdateRenderingBuffer(false),
	m_needToUpdateTexture(false)
{
	m_transform = new Transform(_position);
}
GameObject::~GameObject()
{

}
bool GameObject::GetIsVisible()
{
	return m_isVisible;
}
void GameObject::SetIsVisible(bool _isVisible)
{
	m_isVisible = _isVisible;
}
void GameObject::AddVertex(Vertex newVertex)
{
	m_vertexes.push_back(newVertex);
}
void GameObject::AddSurfaces(std::vector<std::vector<int>>newSurfaces)
{
	for (int i = 0;i < newSurfaces.size();++i)
	{
		m_surfaces.push_back(newSurfaces[i]);
	}

	//Update vertex normals
	for (int i = 0;i < m_vertexes.size();++i)
	{
		m_vertexes[i].SetVertexNormal(0.0f, 0.0f, 0.0f);
	}
	for (int i = 0;i < m_surfaces.size();++i)
	{
		int vertex0 = m_surfaces[i][0];
		int vertex1 = m_surfaces[i][1];
		int vertex2 = m_surfaces[i][2];
		DirectX::XMFLOAT3 vertex0Normal = m_vertexes[vertex0].GetVertexNormal();
		DirectX::XMFLOAT3 vertex1Normal = m_vertexes[vertex1].GetVertexNormal();
		DirectX::XMFLOAT3 vertex2Normal = m_vertexes[vertex2].GetVertexNormal();
		DirectX::XMFLOAT3 vertex0Position = m_vertexes[vertex0].GetPosition();
		DirectX::XMFLOAT3 vertex1Position = m_vertexes[vertex1].GetPosition();
		DirectX::XMFLOAT3 vertex2Position = m_vertexes[vertex2].GetPosition();
		DirectX::XMVECTOR vertex0PositionVector = DirectX::XMLoadFloat3(&vertex0Position);
		DirectX::XMVECTOR vertex1PositionVector = DirectX::XMLoadFloat3(&vertex1Position);
		DirectX::XMVECTOR vertex2PositionVector = DirectX::XMLoadFloat3(&vertex2Position);
		DirectX::XMVECTOR e0 = DirectX::XMVectorSubtract(vertex1PositionVector,vertex0PositionVector);
		DirectX::XMVECTOR e1 = DirectX::XMVectorSubtract(vertex2PositionVector, vertex0PositionVector);
		DirectX::XMVECTOR faceNormal = DirectX::XMVector3Cross(e0, e1);
		m_vertexes[vertex0].SetVertexNormal(DirectX::XMVectorAdd(DirectX::XMLoadFloat3(&vertex0Normal), faceNormal));
		m_vertexes[vertex1].SetVertexNormal(DirectX::XMVectorAdd(DirectX::XMLoadFloat3(&vertex1Normal), faceNormal));
		m_vertexes[vertex2].SetVertexNormal(DirectX::XMVectorAdd(DirectX::XMLoadFloat3(&vertex2Normal), faceNormal));
	}
	for (int i = 0;i < m_vertexes.size();++i)
	{
		DirectX::XMFLOAT3 vertexNormal = m_vertexes[i].GetVertexNormal();
		DirectX::XMVECTOR vertexNormalVector = DirectX::XMLoadFloat3(&vertexNormal);
		vertexNormalVector = DirectX::XMVector3Normalize(vertexNormalVector);
		m_vertexes[i].SetVertexNormal(vertexNormalVector);
	}
	m_needToUpdateRenderingBuffer = true;
}

GameObject* GameObject::CreateCube(std::vector<float>_position, std::string _name)
{
	
	GameObject* newGameObject = new GameObject(_position, _name);
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, -0.5, -0.5},0.0f,1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, 0.5, -0.5},0.0f,0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, 0.5, -0.5},1.0f,0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, -0.5, -0.5},1.0f,1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, -0.5, -0.5}, 0.0f, 1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, 0.5, -0.5}, 0.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, 0.5, 0.5}, 1.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, -0.5, 0.5}, 1.0f, 1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, -0.5, 0.5}, 0.0f, 1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, 0.5, 0.5}, 0.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, 0.5, 0.5}, 1.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, -0.5, 0.5}, 1.0f, 1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, -0.5, 0.5}, 0.0f, 1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, 0.5, 0.5}, 0.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, 0.5, -0.5}, 1.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, -0.5, -0.5}, 1.0f, 1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, 0.5, -0.5}, 0.0f, 1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, 0.5, 0.5}, 0.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, 0.5, 0.5}, 1.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, 0.5, -0.5}, 1.0f, 1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, -0.5, 0.5}, 0.0f, 1.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{-0.5, -0.5, -0.5}, 0.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, -0.5, -0.5}, 1.0f, 0.0f));
	newGameObject->AddVertex(Vertex(std::vector<float>{0.5, -0.5, 0.5}, 1.0f, 1.0f));
	std::vector<std::vector<int>>surfaces;
	surfaces.push_back(std::vector<int>{0, 1, 2});
	surfaces.push_back(std::vector<int>{0, 2, 3});
	surfaces.push_back(std::vector<int>{4, 5, 6});
	surfaces.push_back(std::vector<int>{4, 6, 7});
	surfaces.push_back(std::vector<int>{8, 9, 10});
	surfaces.push_back(std::vector<int>{8, 10, 11});
	surfaces.push_back(std::vector<int>{12, 13, 14});
	surfaces.push_back(std::vector<int>{12, 14, 15});
	surfaces.push_back(std::vector<int>{16, 17, 18});
	surfaces.push_back(std::vector<int>{16, 18, 19});
	surfaces.push_back(std::vector<int>{20, 21, 22});
	surfaces.push_back(std::vector<int>{20, 22, 23});
	newGameObject->AddSurfaces(surfaces);
	return newGameObject;
}

std::vector<Vertex> GameObject::GetVertexes()
{
	return m_vertexes;
}
std::vector<std::vector<int>> GameObject::GetIndexes()
{
	return m_surfaces;
}
ID3D11Buffer** GameObject::GetVertexBuffer()
{
	return &m_vertexBuffer;
}
ID3D11Buffer** GameObject::GetIndexBuffer()
{
	return &m_indexBuffer;
}
void GameObject::SetVertexBuffer(ID3D11Buffer* vertexBuffer)
{
	m_vertexBuffer = vertexBuffer;
}
void GameObject::SetIndexBuffer(ID3D11Buffer* indexBuffer)
{
	m_indexBuffer = indexBuffer;
}
int GameObject::GetIndexNumber()
{
	return m_surfaces.size() * 3;
}
Material* GameObject::GetMaterial()
{
	return m_material;
}
void GameObject::UseMaterial(Material* material)
{
	m_shaderType = 1;
	m_material = material;
}
void GameObject::UseTexture(std::string ambientMapFileName, std::string diffuseMapFileName, std::string specularMapFileName)
{
	m_shaderType = 2;
	m_ambientTextureFileName = ambientMapFileName;
	m_diffuseTextureFileName = diffuseMapFileName;
	m_specularTextureFileName = specularMapFileName;
	m_needToUpdateTexture = true;
}
bool GameObject::GetNeedToUpdateRenderingBuffer()
{
	return m_needToUpdateRenderingBuffer;
}
void GameObject::SetNeedToUpdateRenderingBuffer(bool status)
{
	m_needToUpdateRenderingBuffer = status;
}
bool GameObject::GetNeedToUpdateTexture()
{
	return m_needToUpdateTexture;
}
void GameObject::SetNeedToUpdateTexture(bool status)
{
	m_needToUpdateTexture = status;
}
std::string GameObject::GetAmbientTextureFileName()
{
	return m_ambientTextureFileName;
}
std::string GameObject::GetDiffuseTextureFileName()
{
	return m_diffuseTextureFileName;
}
std::string GameObject::GetSpecularTextureFileName()
{
	return m_specularTextureFileName;
}
int GameObject::GetShaderType()
{
	return m_shaderType;
}